home *** CD-ROM | disk | FTP | other *** search
/ Greenhouse Effect Detection Expriment / NASA Greenhouse Effect Detection Expriment 1992 - Disc 2.iso / software / dos / cdf22pc / src / tools / cdfbrowx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-02  |  37.6 KB  |  1,411 lines

  1. /******************************************************************************
  2. *
  3. *  NSSDC/CDF                Build screen-arrays for CDFbrowse.
  4. *
  5. *  Version 2.0, 2-Mar-92, ST Systems (STX)
  6. *
  7. *  Modification history:
  8. *
  9. *   V1.0  24-Jan-91, D Grogan    Original version (for CDF V2.0).
  10. *             H Leckner
  11. *   V1.1  30-Jan-91, J Love    Shortened text from CDFerror so as not to
  12. *                overwrite arrays.
  13. *   V1.2  31-Jan-91, J Love    Check for rcode (CDFstatus) < CDF_WARN rather
  14. *                than rcode != CDF_OK to determine if an error
  15. *                has occurred.  Fixed problem with searching
  16. *                for TITLE attribute (pad to 8 characters).
  17. *                Fixed problem with attribute entry lines being
  18. *                too long.
  19. *   V1.3   8-Feb-91, J Love    Limit length of line used to display variable
  20. *                and attribute values.
  21. *   V1.4  21-Mar-91, J Love    Added support for Silicon Graphics (MIPSEB)
  22. *                and removed reference to "strstr".
  23. *   V1.5  26-Mar-91, J Love    Added definition for toupper if SunOS 4.0.3.
  24. *
  25. *   V1.6   6-Jun-91, S Sudarsan Now uses the internal interface for getting 
  26. *                               the header information. Also displays format.
  27. *                Added increment to version display.
  28. *   V1.7  19-Jun-91, J Love    CDF_EPOCH added as a data type.  Fixed problem
  29. *                with FORMAT attribute.  Changed default format
  30. *                for floating point values if FORMAT attribute 
  31. *                not present.
  32. *   V1.8   3-Aug-91, J Love    TRUE/FALSE.  Changed for Cray/UNICOS port.
  33. *                Display CDF_UINT1 & CDF_UCHAR as unsigned.
  34. *                Use 'CDFlib'.  Fixed problem with truncation
  35. *                message being too long.  Reformatted window
  36. *                displayed on CDF open error.
  37. *   V2.0   2-Mar-92, J Love    Modified for IBM-PC port (and IBM-RS6000).
  38. *             H Leckner    CDF V2.2.
  39. *
  40. ******************************************************************************/
  41.  
  42. /* 
  43.     Inquiry module for CDFbrowse that builds screen-arrays to WFL specs.
  44.  
  45.     This module is subordinate to CDFbrowse main program.
  46.     This module never calls WFL, but uses wfl.h constants.
  47.     This module does call CDF and acts as interfacer to CDF for the 
  48.     CDFbrowse main module, which never calls CDF directly.  
  49.  
  50.     There are currently no dependencies on the toolkit per se.
  51.     Some toolkit function are included in different form.
  52.     Requires:
  53.         wfl.h        --standard WFL prototype header
  54.         epochu.obj
  55.         epochu.h    --epochu module and header as
  56.                   revised for CDF v2 release. 
  57.  */
  58.  
  59. #if 0
  60. static int dummyFn() /* debugging use only */
  61. { return;}
  62. #endif
  63.  
  64. #include "wfl.h"
  65.  
  66. #include <stdlib.h>
  67. #include <time.h>
  68. #include <stdio.h>
  69. #include <ctype.h>
  70. #include <string.h>
  71.  
  72. #include "cdfdist.h"
  73. #include "cdfbrow.h"
  74.  
  75.     /* some things that need a limiting value do not have an official one
  76.         in the CDF spec, so here one is decreed for CDFbrowse.
  77.     */
  78. #define BIG_ENOUGH        2048    /* I hope it's big enough */
  79. #define BROWSE_MAX_ATTRS    BIG_ENOUGH
  80.     /* If the CDF has > BROWSE_MAX_ATTRS attributes the program blows up,
  81.        no protection.
  82.        BROWSE_MAX_ATTRS can be replaced by using the dynaptr.h macros
  83.        in the same way that they are used in CDFbrowse, to allocate just
  84.        enough attribute structs according their number.  To do this, you
  85.        must also create a typedef struct ATTR_DEF ATTR_DEF_STRUCT so that
  86.        the macros can expand on the structure type.  That is, 1-token
  87.        expansion is ok; 2-token ("struct ATTR_DEF") is not. -- dg.
  88.     */
  89.  
  90.     /*This union structure supercedes the previous ALLTYPES
  91.         union found in the toolkit and in WFL.
  92.     */
  93. union    DATATYPE_UNION     {             /*    CDF types */
  94.         Schar        byted[BIG_ENOUGH];  /* _BYTE, (_CHAR), _INT1 */
  95.         Uchar        uchard[BIG_ENOUGH]; /* (_UCHAR), _UINT1 */
  96.         short        int2;        /* _INT2    */
  97.         unsigned short    uint2;        /* _UINT2    */
  98.         long        int4;        /* _INT4    */
  99.         unsigned long    uint4;        /* _UINT4    */
  100.         float        real4;        /* _REAL4, _FLOAT */
  101.         double        real8;        /* _REAL8, _DOUBLE, _EPOCH */
  102. };
  103.  
  104. #define pf               printf
  105. #define fpf              fprintf
  106. #define spf         sprintf
  107.  
  108. #define varncTF(string,variance,n) \
  109.     (variance) ? strncat(string, "True ", n) : strncat(string, "false", n)
  110.  
  111. #define FIRST_ELEM        -1      /* Must be negative. look below */
  112. #define EPOCH_TYPE        -777    /* not a CDF type !  An extension */
  113.                         /* See writemTypedValue() */
  114. static struct CDF_DEF    cdfHeaderStruct;  
  115. static struct ATTR_DEF    *attrList[BROWSE_MAX_ATTRS];  /* See warning above */
  116. static struct VAR_DEF    *varList[CDF_MAX_VARS]; 
  117.  
  118. static struct CDF_DEF    *cdfh;
  119. static struct ATTR_DEF    *attr;
  120. static struct VAR_DEF    *var;
  121.  
  122. /*static struct EPOCH    epoch;*/
  123.  
  124. char errorText[CDF_ERRTEXT_LEN+1];                     /* V1.1 */
  125.  
  126. long increment;                                 /* V1.6 */
  127.  
  128. char *dataTypeName( dataType)
  129. long    dataType;
  130. {
  131.     /* return the name-string of the CDF dataType, minus the "CDF" prefix */
  132.     switch( dataType) {
  133.           case CDF_BYTE:    return( "_BYTE  ");
  134.           case CDF_CHAR:    return( "_CHAR  ");
  135.           case CDF_INT1:    return( "_INT1  ");
  136.           case CDF_UCHAR:   return( "_UCHAR ");
  137.           case CDF_UINT1:    return( "_UINT1 ");
  138.           case CDF_INT2:    return( "_INT2  ");
  139.           case CDF_UINT2:    return( "_UINT2 ");
  140.           case CDF_INT4:    return( "_INT4  ");
  141.           case CDF_UINT4:    return( "_UINT4 ");
  142.           case CDF_REAL4:    return( "_REAL4 ");
  143.           case CDF_FLOAT:    return( "_FLOAT ");
  144.           case CDF_REAL8:    return( "_REAL8 ");
  145.           case CDF_DOUBLE:    return( "_DOUBLE");
  146.           case CDF_EPOCH:    return( "_EPOCH ");
  147.           default:        return( "unknown");
  148.     }
  149. } /* end dataTypeName */
  150.  
  151.  
  152. long dataTypeSizeof( dataType)
  153. long dataType;
  154. {
  155.     /* return the length of a CDF dataType */
  156.     switch( dataType) {
  157.           case CDF_BYTE:
  158.           case CDF_CHAR:
  159.           case CDF_INT1:
  160.           case CDF_UCHAR:
  161.           case CDF_UINT1:    return 1;
  162.  
  163.           case CDF_INT2:
  164.           case CDF_UINT2:    return 2;
  165.  
  166.           case CDF_INT4:
  167.           case CDF_UINT4:
  168.           case CDF_REAL4:
  169.           case CDF_FLOAT:    return 4;
  170.  
  171.           case CDF_EPOCH:
  172.           case CDF_REAL8:
  173.           case CDF_DOUBLE:    return 8;
  174.  
  175.           default:        return 0;
  176.     }
  177. } /* end dataTypeSizeof */
  178.  
  179.  
  180. long openCDFtoBrowse (dir, CDFname, out, values_per_record)
  181. char    *dir;
  182. char    *CDFname;
  183. char    *out[];
  184. long     *values_per_record;
  185. {
  186.     /* Open the CDF; read CDF header, attribute, and variable structs;
  187.        Write header text to *out[curRow++,...] page.
  188.     */
  189.     CDFstatus    rcode;
  190.     int        curRow, j, attrNum, dataType, nElements;
  191.     char        msg[CDF_ERRTEXT_LEN+1];                /* V1.1 */
  192.     char         tempString[BIG_ENOUGH];
  193.  
  194.     cdfh = &cdfHeaderStruct;
  195.     curRow = 0;
  196.     spf (out[curRow++],"   CDF Name: %s", CDFname );
  197.  
  198.     strcpy (cdfh->CDFname, dir);
  199.     AppendToDir (cdfh->CDFname, CDFname);
  200.  
  201.     rcode = CDFopen( cdfh->CDFname, &cdfh->id);
  202.  
  203.     if (rcode < CDF_WARN)  {  /*   EARLY RETURN !!!  */    /* V1.2 */
  204.       char *ptr;
  205.       spf (out[curRow++], "   Error --- Cannot open CDF.   ");
  206.       CDFerror (rcode, errorText);                       /*V1.1*/
  207.       if ((ptr = strchr(errorText,':')) != NULL) *ptr = NUL;       /*V1.1*/
  208.       spf (out[curRow++], "   CDF status code: %s   ",errorText);  /*V1.1*/
  209.       return (0);  /* 0 means the CDF is not open .*/
  210.        }
  211.  
  212.         /*  Load CDF header struct */
  213.  
  214.      rcode = CDFlib (SELECT_, CDF_, cdfh->id,
  215.              GET_, CDF_NUMDIMS_,  &cdfh->nDims,
  216.                    CDF_DIMSIZES_, cdfh->dimSizes,
  217.                    CDF_ENCODING_, &cdfh->encoding,
  218.                    CDF_MAJORITY_, &cdfh->majority,
  219.                    CDF_MAXREC_,   &cdfh->maxRec,
  220.                    CDF_NUMVARS_,  &cdfh->nVars,
  221.                    CDF_NUMATTRS_, &cdfh->nAttrs,
  222.                    CDF_FORMAT_,   &cdfh->format,
  223.              NULL_);                /* V1.6 */
  224.  
  225.     if (rcode < CDF_WARN)  {     /*  EARLY RETURN !!! */    /* V1.2 */
  226.       spf (out[curRow++],
  227.          " Error -- Cannot get attributes from CDF %s", CDFname);
  228.       spf (out[curRow++],
  229.          "          on the current directory.");
  230.  
  231.       /*** CDFerror( rcode, out[curRow++]); ***/        /* V1.1 */
  232.       CDFerror (rcode, errorText);                /* V1.1 */
  233.       *strchr(errorText,':') = NUL;                /* V1.1 */
  234.       strcpy (out[curRow++], errorText);            /* V1.1 */
  235.  
  236.       return(0); /* 0 means the CDF is not open */
  237.     }
  238.  
  239.     *values_per_record = 1;
  240.     for(j=0; j<cdfh->nDims; j++)
  241.         *values_per_record = *values_per_record * cdfh->dimSizes[j];
  242.  
  243.     rcode = CDFdoc( cdfh->id, &cdfh->version, &cdfh->release,
  244.                             &cdfh->docText[0]);
  245.     if (rcode < CDF_WARN)  {     /*  EARLY RETURN !!! */    /* V1.2 */
  246.  
  247.       /*** CDFerror( rcode, out[curRow++]); ***/        /* V1.1 */
  248.       CDFerror (rcode, errorText);                /* V1.1 */
  249.       *strchr(errorText,':') = NUL;                /* V1.1 */
  250.       strcpy (out[curRow++], errorText);            /* V1.1 */
  251.  
  252.       return(0); /* 0 means the CDF is not open */
  253.     }
  254.         /*  Fill the header text page */
  255.     spf (out[curRow++]," Dimensions:    %2ld    ", cdfh->nDims);
  256.         /* don't increment curRow yet */
  257.     spf (out[curRow],  "      sizes: [");
  258.     for (j=0; j<cdfh->nDims; j++)  {
  259.        spf (tempString,"%ld", cdfh->dimSizes[j]);
  260.        strcat (out[curRow], tempString);
  261.        if ( j+1 != cdfh->nDims) strcat (out[curRow],",");
  262.     }
  263.         /* resume incrementing curRow */
  264.     strcat (out[curRow++],"]");
  265.     spf (out[curRow++],"    Records:%6ld",        cdfh->maxRec+1);
  266.     spf (out[curRow++]," Attributes:    %2ld",     cdfh->nAttrs);
  267.     spf (out[curRow++],"  Variables:    %2ld",     cdfh->nVars);
  268.     switch( cdfh->encoding) {
  269.         case VAX_ENCODING:
  270.                 spf (out[curRow++],"   encoding: VAX");
  271.                 break;
  272.         case SUN_ENCODING:
  273.                 spf (out[curRow++],"   encoding: Sun");
  274.                 break;
  275.         case MIPSEL_ENCODING:
  276.                 spf (out[curRow++],"   encoding: MIPSEL");
  277.                 break;
  278.         case MIPSEB_ENCODING:                    /* V1.4 */
  279.                 spf (out[curRow++],"   encoding: MIPSEB");
  280.                 break;
  281.         case IBMRS_ENCODING:
  282.                 spf (out[curRow++],"   encoding: IBMRS");
  283.                 break;
  284.         case IBMPC_ENCODING:
  285.                 spf (out[curRow++],"   encoding: IBMPC");
  286.                 break;
  287.         case HP_ENCODING:
  288.                 spf (out[curRow++],"   encoding: HP");
  289.                 break;
  290.         case NETWORK_ENCODING:
  291.                 spf (out[curRow++],"   encoding: Network");
  292.                 break;
  293.         default:
  294.                 spf (out[curRow++],"   encoding: ? Unknown");
  295.                 break;
  296.     }
  297.     switch( cdfh->majority) {
  298.         case ROW_MAJOR:
  299.                 spf (out[curRow++],"   majority: Row");
  300.                 break;
  301.         case COL_MAJOR:
  302.                 spf (out[curRow++],"   majority: Column");
  303.                 break;
  304.         default:
  305.                 spf (out[curRow++],"   majority: ? Unknown");
  306.                 break;
  307.     }
  308.  
  309.       switch( cdfh->format) {                                /* V1.6 */
  310.         case SINGLE_FILE:
  311.                 spf (out[curRow++],"     Format: Single");
  312.                 break;
  313.         case MULTI_FILE:
  314.                 spf (out[curRow++],"     Format: Multi");
  315.                 break;
  316.         default:
  317.                 spf (out[curRow++],"     Format: ? Unknown");
  318.                 break;
  319.     }
  320.  
  321.     rcode = CDFlib (SELECT_, CDF_, cdfh->id,
  322.             GET_, CDF_INCREMENT_, &increment,
  323.             NULL_);                /* V1.6 */
  324.  
  325.     spf (out[curRow++],"    version: %ld.%ld.%ld",
  326.          cdfh->version, cdfh->release, increment);        /* V1.6 */
  327.  
  328.         /* allocate space for attribute and variable structs.
  329.         REPLACE with maocros in dynaptr.h for best practice. --dg.
  330.         These spaces get freed in cdfCloseQuit().
  331.         **/
  332.     for (j=0; j<cdfh->nAttrs; j++)
  333.         {
  334.         attrList[j] = (struct ATTR_DEF *) malloc (sizeof(struct ATTR_DEF));
  335.         if(attrList[j] == NULL)
  336.            {
  337.         printf("BAD MALLOC, attr_num %d",j);
  338.         return(BAD_MALLOC);
  339.            }
  340.         }
  341.     for (j=0; j<cdfh->nVars; j++)
  342.         {
  343.         varList[j] = (struct VAR_DEF *) malloc (sizeof(struct VAR_DEF));
  344.         if(varList[j] == NULL)
  345.            {
  346.         printf("BAD MALLOC, var_num %d",j);
  347.         return(BAD_MALLOC);
  348.            }
  349.         }
  350.     /*----------Load attributes structs **/
  351.  
  352.     for (j=0; j<cdfh->nAttrs; j++)  {
  353.         attr = attrList[j];
  354.         attr->attrNum = j;
  355.         rcode = CDFattrInquire( cdfh->id,
  356.                 attr->attrNum,
  357.                   &attr->name[0],
  358.                   &attr->scope,
  359.                   &attr->maxEntry);
  360.         if (rcode < CDF_WARN)  {            /* V1.2 */
  361.             CDFerror( rcode, msg);
  362.             *strchr(msg,':') = NUL;            /* V1.1 */
  363.             fpf (stderr,"\n%s", msg);
  364.         }
  365.     }
  366.  
  367.     /*----------Load variable structs **/
  368.  
  369.     for (j=0; j<cdfh->nVars; j++)  {
  370.         var = varList[j];
  371.         var->varNum = j;
  372.         rcode = CDFvarInquire( cdfh->id,
  373.                 var->varNum,
  374.                    &var->name[0],
  375.                    &var->dataType,
  376.                    &var->stringSize,
  377.                    &var->recVariance,
  378.                    &var->dimVariances[0]);
  379.         if (rcode < CDF_WARN)  {            /* V1.2 */
  380.             CDFerror( rcode, msg);
  381.             *strchr(msg,':') = NUL;            /* V1.1 */
  382.             fpf (stderr,"\n%s", msg);
  383.         }
  384.  
  385. #if NSSDC_STANDARD
  386.         /* if there is a FORMAT attribute for this variable;
  387.             get it & put it in format string member.
  388.         */
  389.         attrNum = CDFattrNum( cdfh->id, "FORMAT");
  390.         if ( attrNum >= 0) {                /* V1.2 */
  391.             rcode = CDFattrEntryInquire( cdfh->id, attrNum, /* V1.7 */
  392.                 var->varNum, &dataType, &nElements);
  393.             if (rcode > CDF_WARN)                /* V1.7 */
  394.               switch (dataType) {
  395.             case CDF_CHAR:
  396.                 /*  Yes FORMAT exists, so get its value for the
  397.                 variable from CDF, and save in the var->format.
  398.                 */
  399.                 rcode = CDFattrGet( cdfh->id, attrNum,
  400.                         var->varNum, &var->format[0]);
  401.                 if (rcode < CDF_WARN)         /* V1.2 */
  402.                   strcpy (var->format, "");
  403.                 else
  404.                   var->format[nElements] = '\0';   /* V1.7 */
  405.                 break;
  406.             default:
  407.                 strcpy( var->format, "");
  408.                 break;
  409.               }  /* end switch */
  410.             else {                    /* V1.7 */
  411.               strcpy (var->format, "");   /* no entry */
  412.             }
  413.         } else {
  414.             strcpy( var->format, "");     /* no FORMAT */
  415.         }
  416. #else
  417.         strcpy (var->format, "");    /* ignore FORMAT */
  418. #endif
  419.  
  420.     }  /* end for loop thru vars */
  421.  
  422.     /* CDF is open and structs are loaded */
  423.    return ( 1);  /* 1 == OK, the cdf is open. */
  424. } /* end openCDFtoBrowse */
  425.  
  426.  
  427. void cdfCloseQuit ( )
  428. {
  429.     CDFstatus rcode;
  430.     long j;
  431.  
  432.     /*  Free all the space in the attribute and variable lists
  433.      *  and then close the CDF.
  434.      */
  435.     for (j=0; j<cdfh->nAttrs; j++)
  436.         free (attrList[j]);
  437.  
  438.     for (j=0; j<cdfh->nVars; j++)
  439.         free (varList[j]);
  440.  
  441.     rcode = CDFclose ( cdfh->id);
  442.     if(rcode < CDF_OK)printf("Error closing CDF\n");
  443. }  /* end cdfCloseQuit */
  444.  
  445.  
  446. void catAttrEntry(out, cdfh, attr, entryNum, elemNum )
  447. char        *out;
  448. struct CDF_DEF    *cdfh;
  449. struct ATTR_DEF *attr;
  450. long        entryNum;
  451. long         elemNum ;
  452. {
  453. /*
  454.     This function will concatenate the contents of a
  455.     CDF attribute entry to the string *out.
  456.     The elemNum arg is new.  This will display the 0..elemNum-th -1
  457.     element...  The exception is when the datatype is _CHAR or _UCHAR,
  458.     then all elements, the whole string, will be concatenated.
  459.     If the elemNum is == FIRST_ELEM, it is a special signal that means
  460.     concat strings in all their elements as "hooey, dewy, and fooey".
  461.     Otherwise only the elem character is concatenated "h", "o", ...
  462.     This functio also does special things for attributes of EPOCH variables.
  463. */
  464.     CDFstatus        rcode;
  465.     static union DATATYPE_UNION     value, *valPtr;
  466.     char string[BIG_ENOUGH];
  467.     long             item, showStringsByOne;
  468.  
  469.         /* first what dataType ? and how many elements ? */
  470.     rcode = CDFattrEntryInquire( cdfh->id, attr->attrNum, entryNum,
  471.                 &attr->dataType, &attr->nElements);
  472.     if (rcode < CDF_WARN) {                    /* V1.2 */
  473.         CDFerror( rcode, string);
  474.         *strchr(string,':') = NUL;            /* V1.1 */
  475.     }
  476.     if ( dataTypeSizeof( attr->dataType) * attr->nElements > BIG_ENOUGH) {
  477.         sprintf(out,
  478.           "<CDFbrowse.catAttrEntry> Too-large attribute. Tell CDFsupport.");
  479.         return;
  480.     }
  481.     rcode = CDFattrGet( cdfh->id,
  482.             attr->attrNum,
  483.             entryNum,
  484.             &value);
  485.  
  486.     /* re-map according to desired element number, and by the funky rules
  487.         for strings. */
  488.     if (elemNum == FIRST_ELEM) { /* we want horizontal strings and
  489.                     only 1 element for other types */
  490.         showStringsByOne = FALSE;
  491.         item = 0;
  492.     } else { /* print the nth element, but only length 1 for strings */
  493.         showStringsByOne = TRUE;
  494.         item = dataTypeSizeof( attr->dataType) * elemNum;
  495.     }
  496.     valPtr = (union DATATYPE_UNION *) &value.byted[item];
  497.  
  498.     if (rcode < CDF_WARN) {                    /* V1.2 */
  499.         CDFerror( rcode, string);
  500.         *strchr(string,':') = NUL;            /* V1.1 */
  501.     } else {
  502.         /* Special handling for attributes of an EPOCH variable. */
  503.        if ( entryIsaEpoch( attr->dataType) ) {
  504.         writemTypedValue (string, EPOCH_TYPE, 1, valPtr, "");
  505.        } else {  /* not an epoch data */
  506.         if ( showStringsByOne    &&
  507.                     (attr->dataType == CDF_CHAR  ||
  508.                      attr->dataType == CDF_UCHAR ) ) {
  509.             writemTypedValue (string, attr->dataType,
  510.                     1, valPtr, "");
  511.         } else {
  512.             writemTypedValue (string, attr->dataType,
  513.                     attr->nElements, valPtr, "");
  514.         }
  515.        }
  516.     }
  517.     if (strlen(out) + strlen(string) > (SCREEN_WIDTH-2))
  518.       string[(SCREEN_WIDTH-2) - strlen(out)] = NUL;        /* V1.2, V1.3 */
  519.  
  520.     strcat (out, string);
  521. }  /* end catAttrEntry */
  522.  
  523.  
  524. void writemTitle (out)
  525. char    *out[];
  526. {
  527.  
  528.     /* write the title if the TITLE attribute exists.*/
  529.     long attrNum = CDFattrNum( cdfh->id, "TITLE   ");       /* V1.2 */
  530.     if (attrNum < 0) attrNum = CDFattrNum (cdfh->id, "TITLE"); /* V1.2 */
  531.  
  532.     strcpy (out[0], " Title: ");
  533.     if (attrNum < 0)
  534.         strcat (out[0], "--none--");
  535.     else
  536.         catAttrEntry( out[0], cdfh, attrList[attrNum], (long) 0,
  537.             (long) FIRST_ELEM);
  538.     strcat (out[0]," ");
  539. }  /* end writemTitle */
  540.  
  541.  
  542. void writemCopyright (out)
  543. char    *out[];
  544. {
  545.     /* write the copyright notice text, ie, CDFdoc() stuff.
  546.     The leading '\n' must be replaced, and all other '\n' are converted to
  547.     '\0' so that WFL likes it.
  548.     */
  549.     int curRow = 0;
  550.     int line = 0;
  551.     int len, k;
  552.     CDFstatus rcode;
  553.     char *p;
  554.  
  555.     rcode = CDFdoc( cdfh->id, &cdfh->version, &cdfh->release,
  556.             &cdfh->docText[0]);
  557.     if (rcode < CDF_WARN)  {     /*  EARLY RETURN !!! */    /* V1.2 */
  558.         strcpy( out[curRow++], "   Open the CDF first.  ");
  559.  
  560.         /*** CDFerror( rcode, out[curRow++]); ***/    /* V1.1 */
  561.         CDFerror (rcode, errorText);            /* V1.1 */
  562.         *strchr(errorText,':') = NUL;            /* V1.1 */
  563.         strcpy (out[curRow++], errorText);        /* V1.1 */
  564.  
  565.         return;
  566.     }
  567.     len = strlen( cdfh->docText);
  568.     for (k=0; k<len; k++) {    /* make acceptable for WFL menus */
  569.         if ( cdfh->docText[k] == '\n') {
  570.             if (k==0)
  571.                 cdfh->docText[k] = ' ';
  572.             else {
  573.                 cdfh->docText[k] = '\0';
  574.                 line++;
  575.             }
  576.         }
  577.     }
  578.         /* write to the out[] */
  579.     p = &cdfh->docText[0];
  580.     for (k=0; k<line; k++) {
  581.         strcpy( out[curRow++], p);
  582.         len = strlen( p);
  583.         p += len +1;
  584.     }
  585. }  /* end writemCopyright */
  586.  
  587.  
  588. void writemAttrs (out)
  589. char    *out[];
  590. {
  591. /*
  592.     This lists definitions of all attributes to the array *out[].
  593.  */
  594.     long j;
  595.     int curRow = 0;
  596.  
  597.     if (cdfh->nAttrs <= 0)  {  /*   RETURN if no attributes   */
  598.        spf (out[curRow++],
  599.         "    No attributes are defined for this CDF.      ");
  600.        return;
  601.     }
  602.     for (j=0; j<cdfh->nAttrs; j++)  {
  603.         attr = attrList[j];
  604.                         /* prime formatter */
  605.         spf (out[curRow],"%4ld %-16.16s %4ld ",
  606.                 j+1, attr->name, attr->maxEntry+1);
  607.         switch( attr->scope) {
  608.             case GLOBAL_SCOPE:
  609.             strcat (out[curRow], "Global          ");
  610.             break;
  611.             case VARIABLE_SCOPE:
  612.             strcat (out[curRow], "Variable        ");
  613.             break;
  614.             case GLOBAL_SCOPE_ASSUMED:
  615.             strcat (out[curRow], "Assumed Global  ");
  616.             break;
  617.             case VARIABLE_SCOPE_ASSUMED:
  618.             strcat (out[curRow], "Assumed Variable");
  619.             break;
  620.             default:
  621.             strcat (out[curRow], "? Unknown scope");
  622.             break;
  623.         }
  624.         curRow++;
  625.     }  /* end for j */
  626. }   /* end writemAttrs */
  627.  
  628.  
  629. void varName (varNum, variable_name)
  630. long varNum;
  631. char *variable_name;
  632. {
  633.    /*  What's the name of the numbered variable? */
  634.    if (cdfh->nVars > 0  && varNum >= 0 && varNum < cdfh->nVars)
  635.       strcpy (variable_name, varList[varNum]->name);
  636.    else
  637.       strcpy (variable_name, "?NO_SUCH_VAR?");
  638. }  /* end varName */
  639.  
  640. void writemAttrEntries (out, attrNum)
  641. char    *out[];
  642. long     attrNum;
  643. {
  644. /*   nov-1990, heavily modified... -dg.
  645.     This function lists the entries for the attribute to the array out[].
  646.     It only lists the 1st element of each entry, except when dataType ==
  647.     CHAR or UCHAR , then it lists all (in the string array.)
  648. */
  649.     int            curRow = 0;
  650.     CDFstatus         rcode;
  651.  
  652.  
  653.  
  654.     long            entryNum;
  655.     char             eText[CDF_ERRTEXT_LEN+1];         /* V1.1 */
  656.     char            tLine[BIG_ENOUGH], tLine2[BIG_ENOUGH];
  657.     long             dataType, nElements;
  658.  
  659.     if (cdfh->nAttrs == 0) {   /*  EARLY RETURN */
  660.         spf (out[curRow++],
  661.             "    No attributes are defined for this CDF.   ");
  662.         return;
  663.     }
  664.     attr = attrList[attrNum];
  665.     if (attr->maxEntry < 0) {   /*  EARLY RETURN */
  666.         spf (out[curRow++],
  667.             "    No entries are defined.   ");
  668.         return;
  669.     }
  670.     for (entryNum=0; entryNum <= attr->maxEntry; entryNum++)  {
  671.         sprintf( out[curRow], "%3ld ", entryNum+1);
  672.         rcode = CDFattrEntryInquire( cdfh->id, attr->attrNum,
  673.                 entryNum, &dataType, &nElements);
  674.  
  675.         if (rcode >= CDF_OK) {                /* V1.2 */
  676.             switch( attr->scope) {
  677.                 case GLOBAL_SCOPE:
  678.                 case GLOBAL_SCOPE_ASSUMED:
  679.                     strcpy( tLine, "{global} ");
  680.                     break;  /* global case */
  681.  
  682.                 case VARIABLE_SCOPE:
  683.                 case VARIABLE_SCOPE_ASSUMED:
  684.                     varName( entryNum, tLine2 );
  685.                     sprintf( tLine, "{%-16s} ", tLine2);
  686.                     break;  /* variable scope case */
  687.             }  /* end switch */
  688.             strcat( tLine, dataTypeName( dataType) );
  689.             strcat( tLine, "[");
  690.             strcat( out[curRow], tLine);
  691.             sprintf( tLine, "%3ld]: ", nElements);
  692.             strcat( out[curRow], tLine);
  693.  
  694.             catAttrEntry( out[curRow], cdfh, attr, entryNum,
  695.                             (long) FIRST_ELEM);
  696.             switch (dataType) {
  697.                 case CDF_CHAR:
  698.                 case CDF_UCHAR:
  699.                         break; /* do nothing */
  700.                 default:
  701.                     if (nElements > 1)
  702.                         strcat( out[curRow], " {...}");
  703.                     break;
  704.             }
  705.         } else {
  706.             CDFerror( rcode, eText);
  707.             *strchr(eText,':') = NUL;        /* V1.1 */
  708.             strcat( out[curRow], eText);
  709.         } 
  710.         curRow++;
  711.     } /* end entryNum loop */
  712.  
  713. }  /* end writemAttrEntries */
  714.  
  715.  
  716. void writemAttrElems (out, attrNum, entryNum)
  717. char *out[];
  718. long attrNum;
  719. long entryNum;
  720. {
  721. /*   New function for new menu. -dg.
  722.     Writes the elements of an attribute-entry, vertical listing.
  723. */
  724.     int            curRow = 0;
  725.     CDFstatus         rcode;
  726.     long             dataType, nElements, elem;
  727.  
  728.  
  729.  
  730.     char            tLine[BIG_ENOUGH], tLine2[BIG_ENOUGH];
  731.  
  732.     attr = attrList[attrNum];
  733.     rcode = CDFattrEntryInquire( cdfh->id, attr->attrNum,
  734.                 entryNum, &dataType, &nElements);
  735.  
  736.     if (rcode < CDF_WARN) {   /*  EARLY RETURN */        /* V1.2 */
  737.         /*** CDFerror( rcode, out[0]); ***/        /* V1.1 */
  738.         CDFerror (rcode, errorText);            /* V1.1 */
  739.         *strchr(errorText,':') = NUL;            /* V1.1 */
  740.         strcpy (out[0], errorText);            /* V1.1 */
  741.         return;
  742.     }
  743.  
  744.     /* Use the first line to label the box */
  745.     switch( attr->scope) {
  746.         case GLOBAL_SCOPE:
  747.         case GLOBAL_SCOPE_ASSUMED:
  748.             strcpy( tLine, " {global scope}  ");
  749.             break;  /* global case */
  750.  
  751.         case VARIABLE_SCOPE:
  752.         case VARIABLE_SCOPE_ASSUMED:
  753.             varName( entryNum, tLine2 );
  754.             sprintf( tLine, "  {%s}  ", tLine2);
  755.             break;  /* variable scope case */
  756.     }  /* end switch */
  757.     strcat( tLine, dataTypeName( dataType) );
  758.     strcat( tLine, " ");
  759.     strcat( out[curRow++], tLine);
  760.  
  761.     for (elem=0; elem < nElements; elem++) {
  762.         sprintf( tLine, " [%3ld]: ", elem+1);
  763.         strcat( out[curRow], tLine);
  764.         catAttrEntry( out[curRow], cdfh, attr, entryNum, elem);
  765.         curRow++;
  766.     } /* end elem loop */
  767.  
  768. }  /* end writemAttrElems */
  769.  
  770.  
  771.  
  772. void writemVars( out)
  773. char *out[];
  774. {
  775. /*
  776.     This lists definitions of all variables to the array out[][].
  777.  */
  778.     long j, k;
  779.     int curRow = 0;
  780.     char appender[BIG_ENOUGH];
  781.     if (cdfh->nVars == 0) {  /*   RETURN if no variables   */
  782.        spf (out[curRow++],
  783.         "     No variables are defined for this CDF.  ");
  784.        return;
  785.     }
  786.  
  787.     for (j=0; j<cdfh->nVars; j++)  {
  788.         var = varList[j];
  789.                         /* prime formatter */
  790.         spf (out[curRow],"%3ld %-16s  %s", var->varNum+1, var->name,
  791.                     dataTypeName( var->dataType) );
  792.         switch( var->dataType) {
  793.         case CDF_UCHAR:
  794.         case CDF_CHAR:
  795.                         /* prime formatter, strings */
  796.             spf (appender, "[%3ld] ", var->stringSize);
  797.             break;
  798.         default:
  799.                         /* prime formatter, non-char */
  800.             spf (appender, "      ");
  801.             break;
  802.         }
  803.                     /* prime formatter, danglers */
  804.         strcat( out[curRow], appender);
  805.             varncTF (out[curRow], var->recVariance, 5);
  806.             strcat (out[curRow],"  [");
  807.         for (k=0; k<cdfh->nDims; k++) {
  808.                 varncTF (out[curRow], var->dimVariances[k], 1);
  809.                 if ( k+1 != cdfh->nDims) strcat (out[curRow],",");
  810.         }
  811.             strcat (out[curRow],"]");
  812.  
  813.             for (k=0; k< (10 -(cdfh->nDims-1)); k++) 
  814.                 strcat (out[curRow],"  ");
  815.             if (cdfh->nDims > 0) 
  816.         strcat (out[curRow++],"   ");
  817.         else
  818.         strcat (out[curRow++],"  ");
  819.     }    /* end j loop */
  820. }   /* end writemVars */
  821.  
  822.  
  823. void writemVarDef (out, varNum)
  824. char *out[];
  825. long varNum;
  826. {
  827.     /*
  828.     This function lists the variable-scope attributes of a variable to 
  829.     the array *out[].
  830.      */
  831.     int            curRow = 0;
  832.     CDFstatus         rcode;
  833.     long             j, entryNum, attrNum, dataType, nElements;
  834.     long            num_var_attributes;
  835.     char    eText[CDF_ERRTEXT_LEN+1],            /* V1.1 */
  836.         string[BIG_ENOUGH];
  837.  
  838.     if (cdfh->nVars  < 1)   { /*   RETURN if no variables   */
  839.        spf (out[curRow++],
  840.         "     No variables are defined for this CDF.     ");
  841.        return;
  842.     }
  843.  
  844.      if (cdfh->nAttrs < 1)   { /*  EARLY RETURN */
  845.         spf (out[curRow++],
  846.             "    No attributes are defined for this CDF.   ");
  847.         return;
  848.     }
  849.  
  850.         /* count non-global attributes. */
  851.      num_var_attributes = 0;
  852.      for (attrNum=0; attrNum < cdfh->nAttrs; attrNum++)
  853.         if ( attrList[attrNum]->scope == VARIABLE_SCOPE ||
  854.              attrList[attrNum]->scope == VARIABLE_SCOPE_ASSUMED)
  855.                 num_var_attributes++;
  856.  
  857.                 /*  EARLY RETURN!! */
  858.      if (num_var_attributes == 0) {
  859.         spf (out[curRow++],
  860.         "  No VARIABLE_SCOPE attributes apply to this variable.  ");
  861.         return;
  862.     }
  863.  
  864.         /*    Get attribs for this variable         */
  865.     var = varList[varNum];
  866.     entryNum = var->varNum;
  867.  
  868.     for (j=0, attrNum=0; attrNum < cdfh->nAttrs; attrNum++)  {
  869.         attr = attrList[attrNum];
  870.         switch( attr->scope )  {
  871.             case VARIABLE_SCOPE:
  872.             case VARIABLE_SCOPE_ASSUMED:
  873.             j++;
  874.             spf (out[curRow], " %2ld {%-16.16s} ", j, attr->name);
  875.  
  876.             rcode = CDFattrEntryInquire( cdfh->id, attr->attrNum,
  877.                 entryNum, &dataType, &nElements);
  878.             if (rcode < CDF_WARN) {            /* V1.2 */
  879.                 CDFerror( rcode, eText);
  880.                 *strchr(eText,':') = NUL;    /* V1.1 */
  881.                 strcat( out[curRow], eText);
  882.             } else {
  883.                 strcat( out[curRow], dataTypeName( dataType) );
  884.                 sprintf( string, "[%3ld]: ", nElements);
  885.                 strcat( out[curRow], string);
  886.                 catAttrEntry (out[curRow], cdfh,
  887.                     attr, entryNum, (long) FIRST_ELEM);
  888.                 switch (dataType) {
  889.                     case CDF_CHAR:
  890.                     case CDF_UCHAR:
  891.                         break; /* do nothing */
  892.                     default:
  893.                     if (nElements > 1)
  894.                         strcat( out[curRow], " {...}");
  895.                     break;
  896.                 }
  897.             }
  898.             curRow++;
  899.             break;
  900.             default:   /* not variable-scope, skip it */
  901.             break;
  902.         }
  903.     }
  904. }  /* end writemVarDef */
  905.  
  906.  
  907. long productLowerDims(    currentDim, dimSizes)
  908. long currentDim;
  909. long dimSizes[];
  910. {
  911.     /* got guts of this from toolkit.
  912.        Algorithm essentially the same.
  913.        Nov-1990, dg.
  914.     */
  915.     long k, product = 1;
  916.     /*    compute product of all dimension sizes less than
  917.         currentDim-th.
  918.      */
  919.     for (k=0; k<currentDim; k++) {
  920.         if (dimSizes[k] > 0)
  921.         product *= dimSizes[k];
  922.     }
  923.     return product;
  924. }  /* end productLowerDims */
  925.  
  926. long productHigherDims(    currentDim, dimSizes)
  927. long currentDim;
  928. long dimSizes[];
  929. {
  930.     /* new function to work with row-major indexing.
  931.        Nov-1990, dg.
  932.     */
  933.     long k, product = 1;
  934.     /*    compute product of all dimension sizes HIGHER than currentDim.
  935.      */
  936.     for (k=currentDim+1; k<cdfh->nDims; k++) {
  937.         if (dimSizes[k] > 0)
  938.         product *= dimSizes[k];
  939.     }
  940.     return product;
  941. }  /* end productHigherDims */
  942.  
  943. void indexVecColMajor( currentItem, cdfh, iVector, var )
  944. long   currentItem;
  945. struct CDF_DEF *cdfh;
  946. long   iVector[];
  947. struct VAR_DEF *var ;
  948. {
  949.     /* got guts of this from toolkit, previous name computeIndexVector.
  950.        Algorithm is altered to return 0-based indexes.
  951.        Nov-1990, dg.
  952.     */
  953. /*
  954.  *    Convert the currentItem to the index vector for a CDF variable.
  955.  *    The scheme is COLUMN-MAJOR -- Leftmost index varies the fastest.
  956.  */
  957.      long     j, next, index, product;
  958.      long       temp_dimSizes[CDF_MAX_DIMS];
  959.      /*
  960.     Set the temp dimSizes vector by setting the size of
  961.     a dimension to 1 whenever the variable has no variance
  962.     in that dimension.
  963.      */
  964.      for (j=0; j < cdfh->nDims; j++)    {
  965.          /* Zero-initialize the vector */
  966.     iVector[j] = 0;
  967.     if (var->dimVariances[j])
  968.         temp_dimSizes[j] = cdfh->dimSizes[j];
  969.     else
  970.         temp_dimSizes[j] = 1;
  971.      }
  972.  
  973.     /* Compute the index vector, ZERO-base address, column major.
  974.      */
  975.      next = currentItem;
  976.      for (j=cdfh->nDims; j>=0; j--)  {
  977.      product = productLowerDims (j, temp_dimSizes);
  978.      index   = (long) (next / product);
  979.      next    =        (next % product);
  980.      iVector[j] = index;
  981.      }
  982. }  /* end indexVecColMajor */
  983.  
  984.  
  985. void indexVecRowMajor( currentItem, cdfh,  iVector, var )
  986. long   currentItem;
  987. struct CDF_DEF *cdfh;
  988. long   iVector[];
  989. struct VAR_DEF *var;
  990. {
  991.     /* New function based on indexVecColMajor, but indexes Row-Major.
  992.        Algorithm returns 0-based indexes.
  993.        Nov-1990, dg.
  994.     */
  995. /*
  996.  *    Convert the currentItem to the index vector for a CDF variable.
  997.  *    The scheme is ROW-MAJOR -- Rightmost index varies the fastest.
  998.  */
  999.      long     j, next, index, product;
  1000.      long       temp_dimSizes[CDF_MAX_DIMS];
  1001.      /*
  1002.     Set the temp dimSizes vector by setting the size of
  1003.     a dimension to 1 whenever the variable has no variance
  1004.     in that dimension.
  1005.      */
  1006.      for (j=0; j < cdfh->nDims; j++)    {
  1007.          /* Zero-initialize the vector */
  1008.     iVector[j] = 0;
  1009.     if (var->dimVariances[j])
  1010.         temp_dimSizes[j] = cdfh->dimSizes[j];
  1011.     else
  1012.         temp_dimSizes[j] = 1;
  1013.      }
  1014.  
  1015.     /* Compute the index vector, ZERO-base address, row major.
  1016.      */
  1017.      next = currentItem;
  1018.      for (j=0; j<cdfh->nDims; j++)  {
  1019.      product = productHigherDims (j, temp_dimSizes);
  1020.      index   = (long) (next / product);
  1021.      next    =        (next % product);
  1022.      iVector[j] = index;
  1023.      }
  1024. }  /* end indexVecRowMajor */
  1025.  
  1026.  
  1027. int writemVarVals( out, varNum, record, maxLines)
  1028. char *out[];
  1029. long varNum;
  1030. long record;
  1031. long maxLines;
  1032. {
  1033. /*    This function lists the values of the Variable for the record to
  1034.     the array *out[].  However, no more than maxLines will be listed.
  1035.     Record comes in 0-based.
  1036. */
  1037.     int curRow = 0;
  1038.     CDFstatus         rcode;
  1039.     long             j;
  1040.     long             iVector[CDF_MAX_DIMS+1];
  1041.     union DATATYPE_UNION    value;
  1042.  
  1043.     char  string[BIG_ENOUGH];
  1044.     long item, numItems;
  1045.     if (cdfh->nVars == 0)  {  /*   RETURN if no variables   */
  1046.     spf (out[curRow++],
  1047.        "     No variables are defined for this CDF.     ");
  1048.     return (-1);
  1049.     }
  1050.                 /*  RETURN if bad record Number */
  1051.     if (record < 0  ||  record > cdfh->maxRec)  {
  1052.     spf (out[0], "  Record %ld -- Out of Bounds (%ld records in this CDF)  ",
  1053.         record+1, cdfh->maxRec+1);
  1054.     return (-1);
  1055.     }
  1056.  
  1057.     var = varList[varNum];
  1058.     numItems = 1;
  1059.     curRow = 0;
  1060.  
  1061.     /* Compute number of items according to variance vector */
  1062.     for (j=0; j<cdfh->nDims; j++)  {
  1063.     if (var->dimVariances[j])
  1064.         numItems *= cdfh->dimSizes[j];
  1065.     }
  1066.  
  1067.     if (var->recVariance)  {
  1068.     spf (out[curRow++], " %ld items.       Record variance is TRUE.   ",
  1069.                 numItems);
  1070.     }  else  {
  1071.     spf (out[curRow++], " %ld items.       Record variance is FALSE.  ",
  1072.                 numItems);
  1073.     spf (out[curRow++], "  These values constant for all records.    ");
  1074.     }
  1075.  
  1076.     for (item=0; item<numItems; item++)  {
  1077.     if (!var->recVariance)
  1078.         spf (out[curRow], " (%3ld)    *:[", item +1);
  1079.     else
  1080.         spf (out[curRow], " (%3ld)  %ld:[", item +1, record +1);
  1081.  
  1082.         /* optimize the vector for getting the same way the data is
  1083.             stored, either row- or col-major */
  1084.     if (cdfh->majority == COL_MAJOR)
  1085.         indexVecColMajor( item, cdfh, iVector, var);
  1086.     else
  1087.         indexVecRowMajor( item, cdfh, iVector, var);
  1088.  
  1089.     for (j=0; j<cdfh->nDims; j++)  {
  1090.         /* if the variance in this dim is false display
  1091.            wildcard index number.
  1092.         */
  1093.         if ( (iVector[j] == 0) && (!var->dimVariances[j]) )
  1094.         spf (string, "  *");
  1095.         else
  1096.         spf (string, "%3ld", iVector[j] +1);
  1097.  
  1098.         strcat( out[curRow], string);
  1099.         if (j+1 < cdfh->nDims)
  1100.         strcat( out[curRow], ",");
  1101.     }
  1102.     strcat( out[curRow], "]= ");
  1103.  
  1104.     rcode = CDFvarGet( cdfh->id, varNum, record, iVector, &value);
  1105.  
  1106.     if( rcode < CDF_WARN) {                    /* V1.2 */
  1107.         CDFerror( rcode, string);
  1108.         *strchr(string,':') = NUL;            /* V1.1 */
  1109.     } else {
  1110.         if ( varIsaEpoch( var->dataType) ) {
  1111.             writemTypedValue (string, EPOCH_TYPE,
  1112.                 var->stringSize, &value, var->format);
  1113.         } else { /* not an epoch */
  1114.             writemTypedValue (string, var->dataType,
  1115.                 var->stringSize, &value, var->format);
  1116.         }
  1117.     }
  1118.  
  1119.     if (strlen(out[curRow]) + strlen(string) > (SCREEN_WIDTH-2))
  1120.       string[(SCREEN_WIDTH-2) - strlen(out[curRow])] = NUL;       /* V1.3 */
  1121.  
  1122.     strcat( out[curRow], string);
  1123.  
  1124.     if (curRow == maxLines-3)  {       /* whoops */
  1125.        spf (string,    "Listing truncated at %ld lines.", maxLines-3);
  1126.        /* place warning at end of output only, V1.8 */
  1127.        strcat (out[curRow+1], string);
  1128.        item = numItems+1; /* break the loop */
  1129.     }
  1130.     curRow++;
  1131.     } /* end item loop */
  1132.     return (0);  /* means OK */
  1133.  
  1134. }  /* end writemVarVals */
  1135.  
  1136. /*******************/
  1137.  
  1138.  
  1139. long numVars ()
  1140. {
  1141.        /*  How many variables in the current CDF ? */
  1142.    return (cdfh->nVars);
  1143. }  /* end numVars */
  1144.  
  1145.  
  1146. long numAttrs ()
  1147. {
  1148.        /*  How many attributes in the current CDF ? */
  1149.    return (cdfh->nAttrs);
  1150. }  /* end numAttrs */
  1151.  
  1152. long nthVarAttr ( n)
  1153. long n;
  1154. {
  1155.     /* new function, nov-1990, dg. */
  1156.     /* given n (0-based), return the CDF's entry-index to the nth
  1157.        variable-scoped attribute.
  1158.      */
  1159.     long k, nth = -1;
  1160.     for (k=0; k<cdfh->nAttrs; k++) {
  1161.         switch (attrList[k]->scope) {
  1162.             case VARIABLE_SCOPE:
  1163.             case VARIABLE_SCOPE_ASSUMED:
  1164.             nth++;
  1165.             if (nth == n)
  1166.                 return k;
  1167.             break;
  1168.             default:
  1169.             break;
  1170.         }
  1171.     }
  1172.     return -1;  /* -1 mean no var-scope items */
  1173. } /* end nthVarAttr */
  1174.  
  1175.  
  1176. long maxAttrEntry( attrNum)
  1177. long attrNum;
  1178. {
  1179.     /* nov-1990, new function. -dg. */
  1180.     /*  what's the maximum entry for this attribute? */
  1181.    if (numAttrs() > 0)
  1182.     return (attrList[attrNum]->maxEntry);
  1183.    else
  1184.     return -1;
  1185. }  /* end maxAttrEntry */
  1186.  
  1187.  
  1188. long numElemsAttr( attrNum, entryNum)
  1189. long attrNum;
  1190. long entryNum;
  1191. {
  1192.     /* nov-1990, new function. -dg. */
  1193.     /*  How many elements in this attribute, this entry? */
  1194.     CDFstatus rcode;
  1195.     long dataType, nElements;
  1196.     rcode = CDFattrEntryInquire( cdfh->id, attrNum, entryNum,
  1197.                 &dataType, &nElements);
  1198.     if (rcode >= CDF_OK)
  1199.         return nElements;
  1200.     else
  1201.         return (0);
  1202. }  /* end numElemsAttr */
  1203.  
  1204.  
  1205. void attribName (attrNum, attrName)
  1206. long attrNum;
  1207. char *attrName;
  1208. {
  1209.    /*  What's the name of the numbered attribute? */
  1210.    if (cdfh->nAttrs > 0  && attrNum >= 0 && attrNum < cdfh->nAttrs)
  1211.       strcpy (attrName, attrList[attrNum]->name);
  1212.    else
  1213.       strcpy (attrName, "?NO_SUCH_ATTR?");
  1214.    return;
  1215. }  /* end attribName */
  1216.  
  1217.  
  1218.  
  1219.  
  1220. Boolean varIsaEpoch( dataType)
  1221. long dataType;
  1222. {
  1223.     /* Nov-1990, new function,
  1224.        return TRUE iff this is an EPOCH
  1225.     */
  1226.     switch (dataType) {
  1227.         case CDF_EPOCH:
  1228.          return TRUE;                    /* ...V1.7 */
  1229.  
  1230.         default:
  1231.         break;
  1232.     }
  1233.     return FALSE;
  1234. }  /* end varIsaEpoch */
  1235.  
  1236.  
  1237. Boolean entryIsaEpoch(dataType)
  1238. long dataType;
  1239. {
  1240.     /* Nov-1990, new function,
  1241.        return TRUE iff this Attribute Entry is an EPOCH
  1242.     */
  1243.     switch (dataType) {                    /* V1.7 */
  1244.         case CDF_EPOCH:
  1245.          return TRUE;                    /* ...V1.7 */
  1246.  
  1247.         default:    /* no such thing as a Global-scope EPOCH.  would be
  1248.             nice however */        /* says who?, V1.7 */
  1249.         break;
  1250.     }
  1251.     return FALSE;
  1252. }  /* end entryIsaEpoch */
  1253.  
  1254.  
  1255. void writemTypedValue(out, dataType, numBytes, valuePtr, passedfmt)
  1256. char *out;
  1257. long dataType;
  1258. long numBytes;
  1259. void *valuePtr;
  1260. char passedfmt[];    /* will be "" if FORMAT attribute/entry not present
  1261.                or is to be ignored */
  1262. {
  1263.     /* revised, inproved for version 2 types from putValueMemory().
  1264.        Formats a CDF value according to CDF dataType and numBytes,
  1265.        writes the  string version to out[].
  1266.        passedfmt is a FORTRAN format string, or "" for defaults.
  1267.        The complication is translating the Fortran to C formatters.
  1268.        Note special non-CDF type, EPOCH_TYPE for readable epoch values.
  1269.     */
  1270.     long formatType = 'D';  /* NOT for decimal; for default in each type */
  1271.     char format[32];/* = "%";*/
  1272.     char fmtTMP[32];/* = "";*/
  1273.     char fmt[32];/* = "";*/
  1274.     long  j, k=0;
  1275.     union DATATYPE_UNION *dtu;
  1276.  
  1277.     strcpy(format,"%");
  1278.     fmtTMP[0] = '\0';
  1279.     fmt[0] = '\0';
  1280.     strcpy( fmt, passedfmt);
  1281.     for (k=0; k<strlen(fmt); k++)
  1282.         if (fmt[k] >= 'a' && fmt[k] <= 'z')
  1283.             fmt[k] = toupper(fmt[k]);
  1284.  
  1285.     if ( strchr(fmt, 'E') != NULL)                /* V1.4 */
  1286.         formatType = 'E';
  1287.  
  1288.     if ( strchr(fmt, 'F') != NULL)                /* V1.4 */
  1289.         formatType = 'F';
  1290.  
  1291.     if ( strchr(fmt, 'G') != NULL)                /* V1.4 */
  1292.         formatType = 'G';
  1293.  
  1294.     for (j=0, k=0; j<strlen( fmt); j++) {
  1295.         if ( (isdigit(fmt[j])) || (fmt[j]=='.') ||
  1296.               (fmt[j] == '+')  || (fmt[j]=='-') )    {
  1297.            fmtTMP[k] = fmt[j];
  1298.            k++;
  1299.         }
  1300.     }
  1301.     fmtTMP[k] = '\0';
  1302.  
  1303.     strcat (format, fmtTMP);
  1304.         /* the format string now has "%" or "%8.2", etc. prefixes
  1305.            for the d,f,s, etc... printf formatters.
  1306.          */
  1307.     dtu = (union DATATYPE_UNION *) valuePtr;
  1308.  
  1309.     switch (dataType)  {
  1310.         case CDF_BYTE:
  1311.         case CDF_INT1:        /* always d format */
  1312.             strcat (format, "d");
  1313.             sprintf (out, format, dtu->byted[0]);
  1314.             break;
  1315.         case CDF_UINT1:
  1316.             strcat (format, "u");
  1317.             sprintf (out, format, dtu->uchard[0]);
  1318.             break;
  1319.         case CDF_INT2:      /* always d format */
  1320.             strcat (format, "d");
  1321.             sprintf (out, format, dtu->int2);
  1322.             break;
  1323.         case CDF_UINT2:     /* always u format */
  1324.             strcat (format, "u");
  1325.             sprintf (out, format, dtu->uint2);
  1326.             break;
  1327.         case CDF_INT4:     /* always ld format */
  1328.             strcat (format, "ld");
  1329.             sprintf (out, format, dtu->int4);
  1330.             break;
  1331.         case CDF_UINT4:     /* always lu format */
  1332.             strcat (format, "lu");
  1333.             sprintf (out, format, dtu->uint4);
  1334.             break;
  1335.         case CDF_FLOAT:
  1336.         case CDF_REAL4:    /* three formats */
  1337.             switch ( formatType) {
  1338.                 case 'E':
  1339.                     strcat (format, "E");
  1340.                     break;
  1341.                 case 'F':
  1342.                     strcat (format, "f");
  1343.                     break;
  1344.                 default:
  1345.                     /* strcat (format, "G"); */
  1346.                     if (dtu->real4 < -1000000000.0 ||
  1347.                         dtu->real4 >  1000000000.0)
  1348.                       strcat (format, "E");
  1349.                     else
  1350.                       strcat (format, "f");
  1351.                     break;
  1352.             }
  1353.             sprintf (out, format, dtu->real4);
  1354.             break;
  1355.           case CDF_DOUBLE:
  1356.           case CDF_REAL8:
  1357.             switch ( formatType) {
  1358.                 case 'E':
  1359.                     strcat (format, "E");
  1360.                     break;
  1361.                 case 'F':
  1362.                     strcat (format, "f");
  1363.                     break;
  1364.                 default:
  1365.                     /* strcat (format, "G"); */
  1366.                     if (dtu->real8 < -1000000000.0 ||
  1367.                         dtu->real8 >  1000000000.0)
  1368.                       strcat (format, "E");
  1369.                     else
  1370.                       strcat (format, "f");
  1371.                     break;
  1372.             }
  1373.             sprintf (out, format, dtu->real8);
  1374.             break;
  1375.           case CDF_CHAR:
  1376.             if (numBytes > SCREEN_WIDTH)
  1377.                 sprintf (format, "\"%%.%ds\"",
  1378.                         SCREEN_WIDTH);
  1379.             else
  1380.                 sprintf (format, "\"%%.%lds\"", numBytes);
  1381.             sprintf (out, format, dtu->byted);
  1382.             break;
  1383.           case CDF_UCHAR:
  1384.             if (numBytes > SCREEN_WIDTH)
  1385.                 sprintf (format, "\"%%.%ds\"",
  1386.                         SCREEN_WIDTH);
  1387.             else
  1388.                 sprintf (format, "\"%%.%ds\"", numBytes);
  1389.             sprintf (out, format, dtu->uchard);
  1390.             break;
  1391.           case EPOCH_TYPE:    /* not a true CDF built-in type --- a possible
  1392.                 conflict will occur if a CDF type has the same
  1393.                 value.  However, the compiler should not allow
  1394.                 duplicate case values.  At least the VAX does
  1395.                 not.  -- dg.
  1396.                 */
  1397.             {    struct EPOCH epoch;
  1398.                 epoch.tSince0 = dtu->real8;
  1399.                 sprintf( out, "%s", epochString( &epoch));
  1400.             }
  1401.             break;
  1402.           default:
  1403.             sprintf (out, "<writemTypedValue> BAD dataType = %s\n",
  1404.                           dataTypeName( dataType) );
  1405.             break;
  1406.           } /* end switch */
  1407.  
  1408. }  /* end writemTypedValue */
  1409.  
  1410.  
  1411.